package posts

import (
	"context"
	"fmt"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/forum/model"
	"mall/service/forum/rpc/internal/svc"
	"mall/service/forum/rpc/types/forum"

	"github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetPostsByIdLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewGetPostsByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPostsByIdLogic {
	return &GetPostsByIdLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// ##25.04.01## 历史遗留文件，暂不处理
func (l *GetPostsByIdLogic) GetPostsById(in *forum.PostsDetailReq) (*forum.PostsInfo, error) {
	if (in.Filter == nil || len(*in.Filter) == 0) && (in.Id == nil || *in.Id == 0) {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	preloadMap, eagerLoadMap := modelx.ParsePreloadAndEagerLoad(in.Preload, in.EagerLoad)
	logrus.Info(fmt.Sprintf("GetPostsById preloadMap: %+v", preloadMap))

	logrus.Info(fmt.Sprintf("GetPostsById eagerLoadMap: %+v", eagerLoadMap))

	forumPostEntityName := model.RpcEntityNames.ForumPost
	if _, ok := model.RpcEntityPreloadMap[forumPostEntityName]; !ok {
		return &forum.PostsInfo{}, nil
	}

	forumPostRepositoryName := model.RepositoryNames.ForumPost
	columnMap, ok := model.RepositoryPreloadMap[forumPostRepositoryName]
	if !ok {
		return &forum.PostsInfo{}, nil
	}

	var post *model.ForumPost
	if in.Id != nil && *in.Id > 0 {
		data, err := l.svcCtx.Post.FindOne(l.ctx, *in.Id)
		if err != nil {
			return nil, err
		}

		post = data
	} else {
		var selectCols []string
		if preloadFields, ok := preloadMap[forumPostEntityName]; ok {
			selectCols = modelx.ParseSelectColumns(preloadFields, columnMap)
		}

		filterMap := modelx.ParseFilter(in.Filter, columnMap)
		logrus.Info(fmt.Sprintf("GetPostsById filterMap: %+v", filterMap))
		if filterMap == nil {
			return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
		}

		orderBy := modelx.ParseSorter(in.Sorter, columnMap)
		logrus.Info(fmt.Sprintf("GetPostsById orderBy: %s", orderBy))
		if len(orderBy) == 0 {
			orderBy = model.ForumPostColumns.PostModifiedDate + " DESC"
		}

		res, _, err := l.svcCtx.Post.GetList(l.ctx, model.M{
			"pageSize": uint64(1),
			"orderBy":  orderBy,
			"select":   strings.Join(selectCols, ","),
		}, -1, filterMap)
		if err != nil {
			return nil, err
		}

		if len(res) == 0 {
			return &forum.PostsInfo{}, nil
		}

		post = res[0]
	}
	if post == nil {
		return &forum.PostsInfo{}, nil
	}

	if post.PostStatus == uint8(globalkey.StatusDeleted) {
		return &forum.PostsInfo{}, nil
	}

	if in.VisitorId != nil && *in.VisitorId != post.PostAuthorID && post.PostStatus != uint8(globalkey.StatusApproved) {
		return &forum.PostsInfo{}, nil
	}

	pid := post.PostID
	var media []*forum.MediaInfo
	var meta []*forum.MetaInfo
	subEntitySettingMap := make(map[string]map[string]*model.ColumnSetting)
	if eagerLoadEntities, ok := eagerLoadMap[forumPostEntityName]; ok {
		for _, entity := range eagerLoadEntities {
			if entitySettingMap, ok := model.RpcEntityPreloadMap[entity]; ok {
				subEntitySettingMap[entity] = entitySettingMap
			}
		}
	}
	forumMediaEntityName := model.RpcEntityNames.ForumMedia
	//有照片就进行查询
	if in.WithMedia != nil && *in.WithMedia > 0 {
		if post.PhotoCount > 0 {
			if _, ok := subEntitySettingMap[forumMediaEntityName]; ok {
				forumMediaRepositoryName := model.RepositoryNames.ForumMedia
				subPreloadFields, hasSubPreloadFields := preloadMap[forumMediaEntityName]
				subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[forumMediaRepositoryName]
				if hasSubPreloadFields && hasSubColumnMap {
					subSelectCols := modelx.ParseSelectColumns(subPreloadFields, subColumnMap)

					mediaFilterMap := make(map[string]map[string][]any)
					mediaFilterMap[model.ForumAttachmentRelationshipColumns.ObjectID] = map[string][]any{
						"equalTo": {pid},
					}
					mediaFilterMap[model.ForumAttachmentRelationshipColumns.ObjectType] = map[string][]any{
						"equalTo": {globalkey.AttachmentLogTypeForumPost},
					}
					orderBy := model.ForumAttachmentRelationshipColumns.AttachmentThumbnail + " DESC," +
						model.ForumAttachmentRelationshipColumns.AttachmentOrder
					mediaList, _, err := l.svcCtx.Post.GetMedia(l.ctx, model.M{
						"orderBy": orderBy,
						"select":  strings.Join(subSelectCols, ","),
					}, -1, mediaFilterMap)
					if err != nil {
						return nil, err
					}
					if len(mediaList) > 0 {
						for _, v := range mediaList {
							media = append(media, &forum.MediaInfo{
								Uid:       &v.AttachmentRelationshipID,
								Id:        pointy.GetPointer(strconv.FormatUint(v.AttachmentID, 10)),
								Uri:       &v.AttachmentSource,
								Url:       &v.AttachmentImageURL,
								Thumbnail: pointy.GetPointer(uint32(v.AttachmentThumbnail)),
								Order:     pointy.GetPointer(uint32(v.AttachmentOrder)),
								AltText:   &v.AttachmentImageAlt,
								MetaData:  &v.AttachmentImageMeta,
							})
						}
					}
				}
			}
		}
	}

	//查询meta  包括点赞量  收藏量等
	forumPostMetaEntityName := model.RpcEntityNames.ForumPostMeta
	if in.WithMeta != nil && *in.WithMeta > 0 {
		if subPreloadFields, ok := preloadMap[forumPostMetaEntityName]; ok {
			var metaKeys []any
			for _, field := range subPreloadFields {
				metaKeys = append(metaKeys, field)
			}
			if len(metaKeys) > 0 {
				metaFilterMap := make(map[string]map[string][]any)
				metaFilterMap[model.ForumPostMetumColumns.PostID] = map[string][]any{
					"equalTo": {pid},
				}
				metaFilterMap[model.ForumPostMetumColumns.MetaKey] = map[string][]any{
					"in": metaKeys,
				}
				metaList, _, err := l.svcCtx.Post.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
				if err != nil && err != model.ErrNotFound {
					return nil, err
				}
				for _, v := range metaList {
					meta = append(meta, &forum.MetaInfo{
						Id:    &v.MetaID,
						Key:   &v.MetaKey,
						Value: &v.MetaValue.String,
					})
				}

			}
		}
	}

	//todo 待定
	if in.SearchLogId != nil {
		var visitorId uint64
		if in.VisitorId != nil {
			visitorId = *in.VisitorId
		}
		var platformId uint
		if in.PlatformId != nil {
			platformId = uint(*in.PlatformId)
		}
		l.svcCtx.ForumUser.InsertClickLog(l.ctx, &model.ForumUserClickLog{
			UserID:      visitorId,
			PlatformID:  platformId,
			SearchLogID: *in.SearchLogId,
			ObjectID:    pid,
			ObjectType:  uint16(globalkey.AttachmentLogTypeForumPost),
			CreatedAt:   time.Now(),
		})
	}

	return &forum.PostsInfo{
		Id:             pointy.GetPointer(pid),
		ForumId:        &post.ForumID,
		TopicId:        &post.TopicID,
		ParentId:       &post.ParentID,
		AuthorId:       &post.PostAuthorID,
		AuthorNickname: &post.PostAuthorNickname,
		AuthorAvatar:   &post.PostAuthorAvatar,
		AuthorIP:       &post.PostAuthorIP,
		AuthorRankId:   pointy.GetPointer(uint32(post.PostAuthorRankID)),
		AuthorRoleId:   pointy.GetPointer(uint32(post.PostAuthorRoleID)),
		PostTitle:      &post.PostTitle,
		PostContent:    &post.PostContent,
		PhotoCount:     pointy.GetPointer(uint32(post.PhotoCount)),
		Status:         pointy.GetPointer(uint32(post.PostStatus)),
		CommentStatus:  pointy.GetPointer(uint32(post.CommentStatus)),
		Meta:           meta,
		Media:          media,
		CreatedAt:      pointy.GetPointer(modelx.FormatTime(post.PostDate, "")),
		UpdatedAt:      pointy.GetPointer(modelx.FormatTime(post.PostModifiedDate, "")),
		DeletedAt:      pointy.GetPointer(modelx.FormatNullDotTime(post.DeletedAt, "")),
	}, nil
}
